iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Modern Web

今晚,我想來點Blazor系列 第 9

Day 9:Dependency Injection

  • 分享至 

  • xImage
  •  

Dependency Injection(以下簡稱DI)相依性注入,是一種Design Pattern,DI帶來的好處多多,除了能減少耦合,增加元件的可用性,也可以讓單元測試更容易撰寫,這篇我們來學習如何在Blazor運用DI機制。

內建Service

以下3個Service都是內建的,也就是說不用額外註冊或設定,只要在component中注入即可使用。

  • HttpClient:提供請求http資源的方法
  • IJSRuntime:提供Javascript runtime物件,注入後可使用 Javascript
  • NavigationManager:包含處理路由導向和狀態的helper

上述是Blazor內建的Service,如果要使用自訂的Service,也可以使用DI方式取得,那要怎麼用呢? 我們直接進入實例,這個例子很單純,在專案中加入一個MovieRepository,透過MovieRepository取的電影清單後顯示到頁面上。

  1. 建立MovieDTO
public class MovieDTO
{
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime ReleaseDate { get; set; }
}

2.建立IMovieRepository,其中有一個GetMovies方法,再建立一個MovieRepository來實作IMovieRepository,這邊資料部分就不存取DB直接用模擬資料。

public interface IMovieRepository
{
    List<MovieDTO> GetMovies();
}


public class MovieRepository : IMovieRepository
    {
        public List<MovieDTO> AllMovie()
        {
            return new List<MovieDTO>()
            {
                new MovieDTO(){Id=1,Name="Batman : Gothom Knight",ReleaseDate=new DateTime(2020,8,1)},
                new MovieDTO(){Id=2,Name="Batman 2 : Two Face",ReleaseDate=new DateTime(2020,8,1)},
                new MovieDTO(){Id=3,Name="Batman 3 : Joker",ReleaseDate=new DateTime(2020,8,1)}
            };
        }
    }

Service 生命週期

接下來就要在DI註冊IMovieRepository了,在註冊時,我們有3種方式決定物件的生命週期

  1. Singleton — 在第一次request產生物件後就會一直存在,直到整個應用程式關閉,所以只要建立後就會一直共用。
  2. Scoped — 每次request時,都會new一個新的物件,在request期間都會共用該物件,這個物件會在request結束時Dispose。
  3. Transient — 每次要求時就會產生一個物件。

註冊物件

註冊物件的寫法上,有幾種方式。建議使用第一種,指定要使用的介面和實作類別,未來較方便抽換元件。

//指定介面和實作類別
services.AddSingleton<IMovieRepository, MovieRepository>();

//直接註冊new好的物件
MovieRepository movieRepository = new MovieRepository();
services.AddSingleton(movieRepository);

//指定介面和new好的物件
services.AddSingleton<IMovieRepository>(movieRepository);

最後在Blazor Server和Blazor WebAssembly的註冊方式有點不同。
Blazor Server--將註冊語法寫在StartUp.cs的ConfigureServices中

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
            
    //註冊IMovieRepository
    services.AddSingleton<IMovieRepository, MovieRepository>();           
 }

Blazor WebAssembly — 將註冊語法寫在Program.cs的Main方法中

public static async Task Main(string[] args)
{
   var builder = WebAssemblyHostBuilder.CreateDefault(args);
   builder.RootComponents.Add<App>("app");

   builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

   //註冊IMovieRepository
   builder.Services.AddSingleton<IMovieRepository, MovieRepository>();

   await builder.Build().RunAsync();
 }

在Component中注入服務

接下來我們在component中,注入我們剛剛的IMovieRepository。

@page "/movie"
@inject IMovieRepository movieRepository

<div class="container">
    <div class="row">
        <div class="col-8">
            <table class="table table-hover h5">
                <tr class="font-weight-bold">
                    <th>編號</th>
                    <th>電影名稱</th>
                    <th>放映日</th>
                </tr>
                @foreach (var item in movies)
                {
                    <tr>
                        <td>@item.Id</td>
                        <td>@item.Name</td>
                        <td>@item.ReleaseDate.ToShortDateString()</td>
                    </tr>
                }
            </table>
        </div>
    </div>
</div>

@code {

    private List<MovieDTO> movies;

    protected override void OnInitialized()
    {
        base.OnInitialized();

        movies = movieRepository.AllMovie();
    }
}
  • 第2行中,我們使用@inject注入IMovieRepository,後面給一個自取的名字movieRepository
  • @code區塊這邊,在OnInitialized中,透過movieRepository取的電影清單後給movies變數,再用foreach顯示到畫面上。
    https://ithelp.ithome.com.tw/upload/images/20200923/20130058ntk12Hk6G4.png

上一篇
Day 8:Routing
下一篇
Day 10:Component
系列文
今晚,我想來點Blazor30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言